#!/usr/bin/perl 
use vars qw(@configs $conf);

my $info = q|
#################################################
[Esempio:] accrocco.pl cfg.crud.pl

-------------
Operazioni di base
-------------
	- legge il nome del file di configurazione dalla riga di comando.
		- Il file di configurazione � un file perl che imposta un hash di configurazione.
	
	- legge "parameters" dell'utente tramite require del file perl di configurazione.	
		- Nei parametri sono fondamentali gli hash $p->{'src'} e $p->{'dst'}  
		- $p{'placeholder-<gen,new,fr>'}: prefissi dei segnaposto delimitanti le stringhe da estrarre e processare
		
	- elabora e trasforma i parameters, creando i parameters finali.  
	
	- crea porzioni di codice usando i parametri 
	- inserisce tali porzioni in un hash %codice.
	- legge "new-files": files da creare e sostituire
	- legge "findreplace-files": files su cui cercare porzioni di codice e applicare find-replace
	- legge "target-files": files su cui eseguire le trasformazioni
	
-------------
NOTE SUI SEGNAPOSTO
-------------
	I segnaposti sono inseriti nei commenti e hanno una forma del tipo:
		AAA:BBB:CCC:OPZstart:OPZ2:
	dove 
		AAA=placeholder, BBB=nomeentita o 'new', CCC=nome descrittivo
	I parametri OPZstart  sono opzionali. 
	OPZstart=start o stop, e viene utilizzato per delimitare piu' righe di testo.
	Inoltre, una riga con segnaposto 'new' puo' contenere la stringa new(X). Il valore X puo essere 
		- delete:  viene eliminata la riga col segnaposto
		- '$p{xxx}': nel segnaposto, il valore ':new:' viene sostituito col valore della variabile perl

	Esempi di segnaposti con placeholder=crud
		// crud:circo:action:start
		// crud:circo:action:stop 
	esempi con :new:
		/* crud:new:form: */
		<!-- [crud:new:form1:]  new(delete)  -->
		//  [crud:new:form2:]  new($p{nomeentita} ) -->

-------------
note di dettaglio. Da rivedere
-------------
- crea %p. 
	L'hash ottenuto da "parameters" e trasformato dalla perl-library.
	$p{k}=v.
	k=nome parametro
	v=valore parametro eventualmente generato o trasformato da funzioni perl.
	
- crea %codice
	L'hash delle porzioni di codice generato dalla perl-library.
	$codice{k}=v.
	k=nome gen eventualmente trasformato utilizzando %p. tale nome corrisponde ad un segnaposto.
	v=stringa generata utilizzando %p ed eventualmente codice perl.

- crea %targetFile da target-files

- ELABORA TARGET-FILES:
	per ogni F in "target-files", F dovra' essere cosi processato: 
	- vengono estratte le stringhe delimitate dai segnaposti contenenti 'placeholder'.
	- da %codice viene presa la porzione di codice corrispondente al segnaposto.
	- la porzione viene inserita nel file alla posizione del segnaposto. 
	- il segnaposto di tipo :new: viene lasciato/eliminato/sostituito in base alla presenza della 
	  stringa new(X) nel segnaposto. 
|;


#>>>>>>>	MAIN
###################################################################

#------include librerie sistema
use File::Path; #necessaria per mkpath
use Data::Dumper; #necessaria per debug
use XML::Simple; #necessaria per leggere i file xml di configurazione

#------include librerie gen
#my $dirCfg = $0;$dirCfg =~ s/\/[^\/]+$//;if( $dirCfg eq '' ){$dirCfg ='.';}
#$ENV{GEN_HOME}=$dirCfg;
use lib "./library"; # add this to %INC
push (@INC, "$ENV{'GEN_HOME'}/library");
$ENV{'PERL5LIB'} .= "$ENV{'GEN_HOME'}/library:$ENV{'GEN_HOME'}/conf/crud";

use genfile; 
use genpar; 
use genfr; 
use genutil; 


#------verifica parametri passati
checkInit();

# leggo i parameters dal file di configurazione
my $cfgfile = $ARGV[0];
require "$cfgfile";	
my $conf = getParameters( \@configs ); #print Dumper($conf); die (1);

# eseguo i require per i moduli aggiuntivi.
# necessari per le FUNZIONI BASE:
# setCalculatedParameters( $p ); setCodeGeneration( $p ); 
my $requires=$conf->{'additional-modules'};
foreach my $req (@$requires){
	require "$req";
}

#start firegen
ciclo_generazione( $conf );

###################################################################
#<<<<<<<	FINE MAIN



#------------------------------------------------------------------
#	CICLO PRINCIPALE: CREA-NEW, FIND-REPLACE, GEN
#------------------------------------------------------------------
#	Gestisce l'array 'cicles' realizzando un ciclo di chiamate.
#	Ad ogni iterazione vengono sovrascritti i parametri 
#	di base $p con 
#	quelli definiti all'interno dell'i-esimo 'cicles'
#------------------------------------------------------------------
sub ciclo_generazione {
	my( $conf ) =@_;
	
	my $cicli=$conf->{cicles};
	my @cicli=@$cicli;
	
	foreach my $cicloPar (@cicli ){
		DEBUG( "[ciclo] ============================ \n" );	
		my $p = mergeParameters( $conf, $cicloPar );			#print Dumper($p); die(1);


		# 	FUNZIONI BASE: 
		#		setCalculatedParameters( $p );
		#		setCodeGeneration( $p ); 
		#	set di paramentri ausiliari e creazione delle porzioni da generare
		#	queste devono essere importate nella require definita nel file cfg
		$p 			= setCalculatedParameters( $p );			#print Dumper($p); die(1);
					
		#i 3 step new, find-replace e gen
		stepNewFiles( $p );
		stepFindReplaceFiles( $p );
		stepGenOnTargetFiles( $p );
	}
}

#------------------------------------------------------------------
#	check iniziale
#------------------------------------------------------------------
sub checkInit {
	if( !exists ( $ENV{'GEN_HOME'} ) )  { die( "ERRORE: Variabile di ambiente GEN_HOME non definita\n" ); };
	if( $ARGV[0] eq '' ){	die( $info );}
}

#---------------------------------------------------
#	ELABORAZIONE NEW-FILES:
#	fileDestinazione = $newFile { fileSorgente }
#	FD = $newFile { FS }
#	per ogni FS in "new-files", FS dovra' essere cosi processato: 
#	si crea FD,
#	si copia il contenuto di FS in FD.
#	si esegue find/replace in ogni riga all'interno di FD, usando il contenuto di $p->{src} e $p->{dst} ,
#	ovvero
#	si cerca ogni valore in $p->{src} e lo si sostituisce con il corrispondente valore in $p->{dst} 
#	
#---------------------------------------------------
sub stepNewFiles {
	my ( $p ) = @_;
	#	use Data::Dumper;	print Dumper($p);	die(1);
	my $newFile = getNewFilesHash( $p->{'new-files'}, $p );
	my ($src, $dst);
	DEBUG( "[step]: stepNewFiles \n" );	
	foreach $src (keys(%$newFile)) {
		$dst = $newFile->{$src};
		
		if ( $p->{operation} =~ /force_overwrite/) {
			genfile::copia( $src, $dst );
		}else{		
			genfile::copiaSeNonEsiste( $src, $dst );		
		}
		#genfile::copiaSeNonEsiste( $src, $dst );
		#genfile::copia( $src, $dst );
		src2dst_file( $p->{src}, $p->{dst}, $dst );
	}
}

#---------------------------------------------------
#	ELABORAZIONE FINDREPLACE-FILES
#	per ogni F in "findreplace-files", F dovra' essere cosi processato: 
#	- elimina_segnaposti_per_evitare_duplicazioni
#	- estrae la porzione di codice delimitata dai segnaposti
#	- esegue find(src)/replace(dst) sulle porzioni di codice estratte
#	- inserisce la porzione sostituita nel file
#
#---------------------------------------------------
sub stepFindReplaceFiles {
	my ( $p ) = @_;
	DEBUG( "[step]: findReplaceFile \n" );	

	my $findReplaceFile=getHashFilesUnixDos( $p->{'findreplace-files'}, $p );	
	
	my $placeholder=$p->{'placeholder-fr'};	
	my $entita  = $p->{'src'}->{'nomeentita'};
	my $placeholderSrc = "$placeholder:$entita";
	$entita  = $p->{'dst'}->{'nomeentita'};
	my $placeholderDst = "$placeholder:$entita";
#return;
	foreach my $f (keys(%$findReplaceFile)) {
		my $porzioni = estrazione_segnaposti( $f, $placeholderSrc, $p->{'src'});
		my $porzioniDst = estrazione_segnaposti( $f, $placeholderDst, $p->{'dst'});
		
		my $rigaInsert = findreplace_delle_stringhe_estratte(
						$f,
						$porzioni, $porzioniDst,
						$p->{'src'}, $p->{'dst'} );
		
		inserisci_stringhe_in_file( $f, $rigaInsert, $p );
	}
}

	
#---------------------------------------------------
#	ELABORAZIONE TARGET-FILES (GEN):
#
#	estrazione stringhe delimitati dai segnaposti
#	costruzioni stringhe 
#	inserimento  stringhe sostituite ed eliminazione delle esistenti
#	
#---------------------------------------------------
sub stepGenOnTargetFiles {
	my ( $p ) = @_;

	DEBUG( "[step]: targetFile \n" );	

	my $targetFile=getHashFilesUnixDos( $p->{'target-files'}, $p ); 		#use Data::Dumper; print Dumper($targetFile); die (1);
	my $placeholder=$p->{'placeholder-gen'};

	my @listaFile = keys(%$targetFile);
	my $numFiles= @listaFile;
	if($numFiles == 0 ){	return;	}
	
	my	$codice = setCodeGeneration( $p );  #print Dumper($codice	); die(1);
	
#DEBUG( "\$params\n" . Dumper($p) . "\n\ncodice\n".Dumper( $codice) );die(1);
#DEBUG( "\n\ncodice\n".Dumper( $codice) );die(1);

	foreach my $f ( @listaFile ) {
		my $porzioni = estrazione_segnaposti( $f, $placeholder, $p );		#print Dumper($porzioni); die(1);
		my $rigaInsert = costruisci_stringhe( $porzioni, $codice, $p );		#print Dumper($rigaInsert); die(1);
		inserisci_stringhe_in_file( $f, $rigaInsert, $p );
	}
}
	

